﻿namespace WMS6.BLL
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Data.Common;
    using WMS6.Common;
    using WMS6.DataEntity;
    using WMS6.DBUtility;
    using WMS6.IDAL;
    using WMS6.DALFactory;

    public class XorderDetailBLL
    {
        private static readonly ICommonMethodDA commonMethod = DataAccess.CreateCommonMethod();
        private string currentWhName;
        private List<string> dataBaseID;
        private static readonly IInvLotDA invlotDA = DataAccess.CreateInvLotDA();
        private static readonly IInvLotLocLpnDA invLotLocLpn = DataAccess.CreateInvLotLocLpnDA();
        private static readonly IInvLotLocLpnDA invLotLocLpnDA = DataAccess.CreateInvLotLocLpnDA();
        private static readonly IInvSkuLocDA InvSkuLoc = DataAccess.CreateInvSkuLocDA();
        private static readonly IInvTransDA invTransDA = DataAccess.CreateInvTransDA();
        private static readonly ILotAttributeDA lotAttributeDA = DataAccess.CreateLotAttributeDA();
        private static readonly ILpnDA lpnDA = DataAccess.CreateLpnDA();
        private PubParasInfo pubParasInfo;
        private static readonly IXorderDetailDA XorderDetailDA = DataAccess.CreateXorderDetailDA();
        private static readonly IXordersDA XordersDA = DataAccess.CreateXordersDA();
        private static readonly IXpickDetailDA XpickDetailDA = DataAccess.CreateXpickDetailDA();

        public XorderDetailBLL()
        {
            this.pubParasInfo = null;
            this.currentWhName = string.Empty;
        }

        public XorderDetailBLL(string currentWH)
        {
            this.pubParasInfo = null;
            this.currentWhName = string.Empty;
            if (!string.IsNullOrEmpty(currentWH))
            {
                this.currentWhName = currentWH;
                this.dataBaseID = commonMethod.GetDataBaseID(currentWH);
                if (this.dataBaseID == null)
                {
                    PublicMethod.GetInstance().ShowAlertMessage("C001");
                }
            }
            else
            {
                PublicMethod.GetInstance().ShowAlertMessage("C002");
            }
        }

        public XorderDetailBLL(PubParasInfo tempPubParasInfo)
        {
            this.pubParasInfo = null;
            this.currentWhName = string.Empty;
            if (!string.IsNullOrEmpty(tempPubParasInfo.CurrentWH))
            {
                this.currentWhName = tempPubParasInfo.CurrentWH;
                this.dataBaseID = commonMethod.GetDataBaseID(tempPubParasInfo.CurrentWH);
                if (this.dataBaseID == null)
                {
                    PublicMethod.GetInstance().ShowAlertMessage("C001", this.pubParasInfo.UserLanguage);
                }
                else
                {
                    this.pubParasInfo = new PubParasInfo();
                    this.pubParasInfo = tempPubParasInfo;
                }
            }
            else
            {
                PublicMethod.GetInstance().ShowAlertMessage("C002", this.pubParasInfo.UserLanguage);
            }
        }

        public XorderDetailInfo GetXorderDetailInfoByID(string xordersID, string lineID)
        {
            return XorderDetailDA.GetXorderDetailByID(xordersID, lineID, this.dataBaseID[0]);
        }

        private string GetXorderStatus(DataBase database, DbTransaction tran, string xorderID, string whLoginID)
        {
            List<XorderDetailInfo> xorderDetailInfo = XorderDetailDA.GetXorderDetailListByID(database, tran, xorderID, whLoginID);
            if ((xorderDetailInfo != null) && (xorderDetailInfo.Count > 0))
            {
                foreach (XorderDetailInfo info in xorderDetailInfo)
                {
                    if ((info.Status == "ALLOCATED") || (info.Status == "PARTALLOCATED"))
                    {
                        return "PartShipped";
                    }
                }
            }
            return "Shipped";
        }

        private string InsertConfirmPickedAndXShippedTrans(DataBase database, DbTransaction tran, XpickDetailInfo xpickDetailInfo, string confirmType, string whLoginID)
        {
            InvTransInfo invTransInfo = new InvTransInfo {
                TransID = commonMethod.GenNextNumStr(database, tran, "INV_TRANS", whLoginID),
                OwnerID = xpickDetailInfo.OwnerID,
                SkuID = xpickDetailInfo.SkuID,
                Lot = xpickDetailInfo.Lot,
                DocID = xpickDetailInfo.PickDetailID,
                DocLineID = 0,
                Qty = xpickDetailInfo.Qty
            };
            if (confirmType.ToUpper() == "XSHIPPED")
            {
                invTransInfo.FromLoc = xpickDetailInfo.ToLoc;
                invTransInfo.FromLpnID = xpickDetailInfo.LpnID;
                invTransInfo.ToLoc = "";
                invTransInfo.ToLpnID = xpickDetailInfo.LpnID;
                invTransInfo.TransType = TransType.Shipment;
                invTransInfo.SourceTransType = TransSourceType.PickingUpdate;
                invTransInfo.Status = TransStatus.OK;
                invTransInfo.TransDate = DateTime.Now;
                invTransInfo.Qty = xpickDetailInfo.Qty * -1M;
            }
            LotAttributeInfo lotInfo = lotAttributeDA.GetLotAttributeByID(database, tran, xpickDetailInfo.Lot, whLoginID);
            if (lotInfo != null)
            {
                invTransInfo.LotAttr01 = lotInfo.LotAttr01;
                invTransInfo.LotAttr02 = lotInfo.LotAttr02;
                invTransInfo.LotAttr03 = lotInfo.LotAttr03;
                invTransInfo.LotAttr04 = lotInfo.LotAttr04;
                invTransInfo.LotAttr05 = lotInfo.LotAttr05;
                invTransInfo.LotAttr06 = lotInfo.LotAttr06;
                invTransInfo.LotAttr07 = lotInfo.LotAttr07;
                invTransInfo.LotAttr08 = lotInfo.LotAttr08;
                invTransInfo.LotAttr09 = lotInfo.LotAttr09;
                invTransInfo.LotAttr10 = lotInfo.LotAttr10;
                invTransInfo.ProduceDate = lotInfo.ProduceDate;
                invTransInfo.ExpiryDate = lotInfo.ExpiryDate;
                invTransInfo.ReceiptDate = lotInfo.ReceiptDate;
                invTransInfo.ExternalLot = lotInfo.ExternalLot;
                invTransInfo.VendorID = lotInfo.VendorID;
            }
            invTransInfo.CaseCnt = 0M;
            invTransInfo.InnerPack = 0M;
            invTransInfo.Pallet = 0M;
            invTransInfo.Cube = 0.0;
            invTransInfo.GrossWgt = 0.0;
            invTransInfo.NetWgt = 0.0;
            invTransInfo.OtherUnit1 = 0.0;
            invTransInfo.OtherUnit2 = 0.0;
            invTransInfo.PackID = xpickDetailInfo.PackID;
            invTransInfo.UomID = xpickDetailInfo.UomID;
            invTransInfo.UomCalc = Convert.ToInt32(xpickDetailInfo.Qty);
            invTransInfo.UomQty = xpickDetailInfo.Qty;
            InvLotInfo invLotInfo = invlotDA.GetInvLotByID(database, tran, xpickDetailInfo.Lot, whLoginID);
            if (invLotInfo != null)
            {
                invTransInfo.UnitPrice = invLotInfo.UnitPrice;
            }
            invTransInfo.CreatedBy = xpickDetailInfo.UpdatedBy;
            invTransInfo.UpdatedBy = xpickDetailInfo.UpdatedBy;
            invTransDA.InsertInvTrans(database, tran, invTransInfo, whLoginID);
            return invTransInfo.TransID;
        }

        public string UpdateXOrdreDetail(XorderDetailInfo xorderDetailInfo)
        {
            DataBase dataBase = new DataBase();
            DbConnection conn = dataBase.connection;
            conn.Open();
            DbTransaction tran = conn.BeginTransaction();
            string XordersID = string.Empty;
            try
            {
                if (XorderDetailDA.UpdateXorderDetail(dataBase, tran, xorderDetailInfo, this.dataBaseID[0]) > 0)
                {
                    XordersID = xorderDetailInfo.LineID.ToString();
                }
                tran.Commit();
            }
            catch (Exception ex)
            {
                tran.Rollback();
                CommonErrorHandler.ErrorHandler(ex, LogType.Error);
            }
            finally
            {
                conn.Close();
            }
            return XordersID;
        }

        public string XorderAllocate(string receiptID, string xorderID, List<string> lineID)
        {
            string whLoginID = this.dataBaseID[0];
            string strTemp = string.Empty;
            string XorderStatus = string.Empty;
            DataBase dataBase = new DataBase();
            DbConnection conn = dataBase.connection;
            conn.Open();
            DbTransaction tran = conn.BeginTransaction();
            try
            {
                OutboundMgtBLL outboundMgtBll = new OutboundMgtBLL(this.pubParasInfo);
                ReceiptLotInfo receiptLotInfo = new ReceiptLotInfo {
                    LotAttr10 = receiptID
                };
                for (int i = 0; lineID.Count > i; i++)
                {
                    XorderDetailInfo xorderDetailInfo = XorderDetailDA.GetXorderDetailByID(xorderID, lineID[i], whLoginID);
                    List<InvLotLocLpnInfo> invLotLocLpninfo = invLotLocLpnDA.GetInvLotLocLpnByLotAttribute(receiptLotInfo, xorderDetailInfo.OwnerID, xorderDetailInfo.SkuID, whLoginID);
                    if ((invLotLocLpninfo != null) && (invLotLocLpninfo.Count > 0))
                    {
                        decimal invQty = 0M;
                        decimal xoriginalQty = xorderDetailInfo.OriginalQty - xorderDetailInfo.ProcessedQty;
                        foreach (InvLotLocLpnInfo invInfo in invLotLocLpninfo)
                        {
                            if (invInfo.Qty > 0M)
                            {
                                XpickDetailInfo xpickDetailInfo;
                                invQty = ((((invInfo.Qty - invInfo.AllocatedQty) - invInfo.PickedQty) - invInfo.ArchiveQty) - invInfo.ExpectedQty) - invInfo.PickinprocessQty;
                                if (invQty >= xorderDetailInfo.OriginalQty)
                                {
                                    invQty = xoriginalQty;
                                    xoriginalQty = 0M;
                                }
                                else if (invQty > 0M)
                                {
                                    xoriginalQty -= invQty;
                                }
                                else
                                {
                                    continue;
                                }
                                InvLotInfo invLotinfo = new InvLotInfo {
                                    Lot = invInfo.Lot,
                                    UpdatedBy = this.pubParasInfo.UserID,
                                    AllocatedQty = invQty,
                                    AllocatedGrossWgt = 0.0,
                                    AllocatedNetWgt = 0.0
                                };
                                invlotDA.UpdateInvLot(dataBase, tran, invLotinfo, InvLotUpdateType.AllocatedQtyWgtOnly, whLoginID);
                                InvLotLocLpnInfo invLotLocLpnInfo = new InvLotLocLpnInfo {
                                    Lot = invInfo.Lot,
                                    Loc = invInfo.Loc,
                                    LpnID = invInfo.LpnID,
                                    AllocatedQty = invQty,
                                    UpdatedBy = this.pubParasInfo.UserID
                                };
                                invLotLocLpnDA.UpdateInvLotLocLpn(dataBase, tran, invLotLocLpnInfo, InvLotLocLpnUpdateType.AllocatedQty, whLoginID);
                                InvSkuLocInfo invskulocInfo = new InvSkuLocInfo {
                                    Loc = invInfo.Loc,
                                    SkuID = invInfo.SkuID,
                                    OwnerID = invInfo.OwnerID,
                                    UpdatedBy = this.pubParasInfo.UserID,
                                    AllocatedQty = invQty
                                };
                                InvSkuLoc.UpdateInvSkuLoc(dataBase, tran, invskulocInfo, InvSkuLocUpdateType.AllocatedQty, whLoginID);
                                xpickDetailInfo = new XpickDetailInfo();
                                xpickDetailInfo.PickDetailID = commonMethod.GenNextNumStr(dataBase, tran, "PICK_DETAIL", whLoginID);
                                xpickDetailInfo.Altsku = "";
                                xpickDetailInfo.PickHeaderID = "";
                                xpickDetailInfo.CartonGroup = "";
                                xpickDetailInfo.CartonType = "";
                                xpickDetailInfo.CaseID = "";
                                xpickDetailInfo.DoCartonize = "";
                                xpickDetailInfo.Door = "";
                                xpickDetailInfo.DoReplenish = "";
                                xpickDetailInfo.DropID = "";
                                xpickDetailInfo.EffectiveDate = DateTime.Now;
                                xpickDetailInfo.LoadID = "";
                                xpickDetailInfo.Loc = invInfo.Loc;
                                xpickDetailInfo.Lot = invInfo.Lot;
                                xpickDetailInfo.LpnID = invInfo.LpnID;
                                xpickDetailInfo.MovedQty = 0M;
                                xpickDetailInfo.OptimizeCop = "";
                                xpickDetailInfo.OrderID = xorderDetailInfo.OrderID;
                                xpickDetailInfo.OrderLineID = xorderDetailInfo.LineID;
                                xpickDetailInfo.OwnerID = xorderDetailInfo.OwnerID;
                                xpickDetailInfo.PackID = "";
                                xpickDetailInfo.PickMethod = "";
                                xpickDetailInfo.Qty = invQty;
                                xpickDetailInfo.Refid = "";
                                xpickDetailInfo.ReplenishZone = "";
                                xpickDetailInfo.Route = "";
                                xpickDetailInfo.SkuID = xorderDetailInfo.SkuID;
                                xpickDetailInfo.Status = PickDetailStatus.New;
                                xpickDetailInfo.Stop = xpickDetailInfo.Stop;
                                xpickDetailInfo.ToLoc = outboundMgtBll.GetDetailPickToLocByFromLoc(dataBase, tran, invInfo.Loc, whLoginID);
                                xpickDetailInfo.UomID = "";
                                xpickDetailInfo.UomQty = 0M;
                                xpickDetailInfo.WaveID = "";
                                xpickDetailInfo.UpdateSource = "";
                                xpickDetailInfo.CreatedBy = this.pubParasInfo.UserID;
                                xpickDetailInfo.UpdatedBy = xpickDetailInfo.CreatedBy;
                                XpickDetailDA.InsertXpickDetail(dataBase, tran, xpickDetailInfo, whLoginID);
                            }
                        }
                        if (xoriginalQty == 0M)
                        {
                            xorderDetailInfo.ProcessedQty = xorderDetailInfo.OriginalQty;
                            xorderDetailInfo.ShippedQty = 0M;
                            xorderDetailInfo.ToProcessQty = 0M;
                            xorderDetailInfo.OpenQty = 0M;
                            xorderDetailInfo.ProcessedQty = xorderDetailInfo.OriginalQty;
                            xorderDetailInfo.Status = "Allocated";
                            if (XorderStatus != "PartAllocated")
                            {
                                XorderStatus = "Allocated";
                            }
                        }
                        else
                        {
                            xorderDetailInfo.ProcessedQty = xorderDetailInfo.OriginalQty - xoriginalQty;
                            xorderDetailInfo.ShippedQty = 0M;
                            xorderDetailInfo.ToProcessQty = xoriginalQty;
                            xorderDetailInfo.OpenQty = xoriginalQty;
                            xorderDetailInfo.Status = "PartAllocated";
                            XorderStatus = "PartAllocated";
                        }
                        XorderDetailDA.UpdateXorderDetail(dataBase, tran, xorderDetailInfo, whLoginID);
                    }
                    strTemp = strTemp + lineID[i] + ",";
                }
                if (string.IsNullOrEmpty(XorderStatus))
                {
                    throw new Exception("分配失败!未找到合适的数据进行分配!");
                }
                XordersDA.UpdateXordersStatus(dataBase, tran, XorderStatus, xorderID, whLoginID, this.pubParasInfo);
                tran.Commit();
            }
            catch (Exception ex)
            {
                tran.Rollback();
                CommonErrorHandler.ErrorHandler(ex, LogType.Error);
            }
            finally
            {
                conn.Close();
            }
            return strTemp;
        }

        public string XPickDetailShipping(List<string> XpickDetailID)
        {
            int temp = 0;
            List<string> intransitIDs = new List<string>();
            string whLoginID = this.dataBaseID[0];
            DataBase dataBase = new DataBase();
            DbConnection conn = dataBase.connection;
            conn.Open();
            DbTransaction tran = conn.BeginTransaction();
            try
            {
                Hashtable ht = new Hashtable();
                for (int i = 0; i < XpickDetailID.Count; i++)
                {
                    XpickDetailInfo xpickDetailInfo = XpickDetailDA.GetXpickDetailByID(dataBase, tran, XpickDetailID[i], whLoginID);
                    XpickDetailDA.UpdateXpickDetailStatus(dataBase, tran, XpickDetailID[i], PickDetailStatus.Shipped, whLoginID, this.pubParasInfo);
                    InvLotInfo invLotinfo = new InvLotInfo {
                        Lot = xpickDetailInfo.Lot,
                        UpdatedBy = this.pubParasInfo.UserID,
                        Qty = xpickDetailInfo.Qty
                    };
                    invlotDA.UpdateInvLot(dataBase, tran, invLotinfo, InvLotUpdateType.XShippedQty, whLoginID);
                    InvLotLocLpnInfo invLotLocLpnInfo = new InvLotLocLpnInfo {
                        Lot = xpickDetailInfo.Lot,
                        Loc = xpickDetailInfo.Loc,
                        LpnID = xpickDetailInfo.LpnID,
                        Qty = xpickDetailInfo.Qty,
                        UpdatedBy = this.pubParasInfo.UserID
                    };
                    invLotLocLpn.UpdateInvLotLocLpn(dataBase, tran, invLotLocLpnInfo, InvLotLocLpnUpdateType.XShippedQty, whLoginID);
                    InvSkuLocInfo invskulocInfo = new InvSkuLocInfo {
                        Loc = xpickDetailInfo.Loc,
                        SkuID = xpickDetailInfo.SkuID,
                        OwnerID = xpickDetailInfo.OwnerID,
                        UpdatedBy = this.pubParasInfo.UserID,
                        Qty = xpickDetailInfo.Qty
                    };
                    InvSkuLoc.UpdateInvSkuLoc(dataBase, tran, invskulocInfo, InvSkuLocUpdateType.XShippedQty, whLoginID);
                    LpnInfo lpnInfo = new LpnInfo();
                    if (!string.IsNullOrEmpty(xpickDetailInfo.LpnID))
                    {
                        lpnInfo = lpnDA.GetLpnByID(dataBase, tran, xpickDetailInfo.LpnID, whLoginID);
                        if (lpnInfo != null)
                        {
                            lpnInfo.Qty -= xpickDetailInfo.Qty;
                            lpnInfo.UpdatedBy = this.pubParasInfo.UserID;
                            lpnDA.UpdateLpn(dataBase, tran, lpnInfo, LpnUpdateType.Qty, whLoginID);
                        }
                    }
                    this.InsertConfirmPickedAndXShippedTrans(dataBase, tran, xpickDetailInfo, "XSHIPPED", whLoginID);
                    XorderDetailDA.UpdateXorderDetailStatusAndQty(dataBase, tran, xpickDetailInfo.OrderID, xpickDetailInfo.OrderLineID.ToString(), "Shipped", xpickDetailInfo.Qty, this.pubParasInfo.UserID, whLoginID);
                    string strStatus = this.GetXorderStatus(dataBase, tran, xpickDetailInfo.OrderID, whLoginID);
                    XordersDA.UpdateXordersStatus(dataBase, tran, strStatus, xpickDetailInfo.OrderID, whLoginID, this.pubParasInfo);
                }
                tran.Commit();
            }
            catch (Exception ex)
            {
                tran.Rollback();
                CommonErrorHandler.ErrorHandler(ex, LogType.Error);
            }
            finally
            {
                conn.Close();
            }
            return temp.ToString();
        }
    }
}

